package cn.com.bsoft.cloud.controller

import cn.com.bsoft.cloud.dao.cloud.ScheduleSiteDao
import cn.com.bsoft.cloud.entity.param.DoctorParam
import cn.com.bsoft.cloud.entity.param.VideoParam
import cn.com.bsoft.cloud.kotlin.AllOpen
import cn.com.bsoft.cloud.model.*
import cn.com.bsoft.cloud.service.CloudAppService
import cn.com.bsoft.cloud.utils.FileUtils
import cn.com.bsoft.cloud.utils.ResultCode
import cn.com.bsoft.cloud.utils.test.HttpUtilTest
import cn.com.bsoft.immunity.utils.postJson
import cn.net.xyan.blossom.kotlin.javaType
import cn.net.xyan.blossom.kotlin.logger
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.model.GetObjectRequest
import com.amazonaws.services.s3.model.ObjectMetadata
import com.amazonaws.services.s3.model.PutObjectRequest
import org.apache.commons.lang3.StringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import java.io.*
import java.net.URL
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.*
import java.util.concurrent.Executors
import java.util.concurrent.ExecutorCompletionService
import java.util.concurrent.ExecutorService




@AllOpen
@Controller
@RequestMapping("/schedule/")
class ScheduleController {

    private val appId="cdadf271070349e25ff3"
    private val secretKey="0cb562bd9bd57e76344ad8621ff7cb2238ce5c29"
    private val tyURL="http://oos-hq-sh.ctyunapi.cn"
//    private val tyURL="http://100.125.81.129"
    private val getURL="http://mh-oos-bucket.oos-hq-sh.ctyunapi.cn/"

    @Autowired
    private val cloudAppService: CloudAppService? = null

    @Autowired
    private val scheduleSiteDao: ScheduleSiteDao? = null

    @ResponseBody
    @RequestMapping("video/status")
    fun updateVideoStatus(@RequestBody videoParam:VideoParam):Map<String, Any?>{
        val regMsg = HashMap<String, Any?>()
        var b =scheduleSiteDao!!.updateVideoStatus(videoParam)
        regMsg.put("code", ResultCode.ERROR)
        regMsg.put("msg", "更新失败！")
        if (b){
            regMsg.put("code", ResultCode.SUCCESS)
            regMsg.put("msg", "更新成功！")
        }
        return regMsg
    }

    @ResponseBody
    @RequestMapping("/login")
    fun checkLogin(@RequestBody checkLoginReq: CheckLoginReq): LoginResult? {

        var login = LoginResult()
        var loginRsp = LoginRsp()
        var doctorParameter = DoctorParameter()
        var imGetParameter = IMGetParameter()
        var imRegisterParameter = IMRegisterParameter()
        var rsp: PersonRsp? = null
        var schedule: DoctorResult? = null
        var requestString: String
        var token: Any? = null

        var urlBase = "https://i.mhwsw.com/test"
        var urlScheduleBase = "https://i.mhwsw.com/cloudOffice"
        var imBase = "https://i.mhwsw.com/im"
        var imKeyURL = "https://i.mhwsw.com/im/appKey"
        var loginURL = URL("$urlBase/person/login")
        var scheduleURL = URL("$urlScheduleBase/clouddrug/findMessByLogname")
        var imGetURL = URL("$imBase/get")
        var imRegisterURL = URL("$imBase/register")

        try {
            rsp = loginURL.postJson<PersonRsp>(checkLoginReq, CheckLoginRsp::class.javaType)
            doctorParameter.logName = rsp?.loginName
        } catch (e: Exception) {
            login.code = ResultCode.ERROR
            login.msg = "登录名或密码错误!"
            return login
        }

        try {
            schedule = scheduleURL.postJson<DoctorResult>(doctorParameter, DoctorResult::class.javaType)
        } catch (e: Exception) {
            login.code = ResultCode.ERROR
            login.msg = "未查询到医生信息!"
            return login
        }

        try {
            requestString = HttpUtilTest.postJson(imKeyURL, "")
        } catch (e: Exception) {
            login.code = ResultCode.ERROR
            login.msg = "获取key失败"
            return login
        }

        var scheduleRecord = schedule!!.result
        imGetParameter.appID = "mh.jieyi"
        imGetParameter.principal = rsp!!.loginName

        try {
            token = imGetURL.postJson<Any>(imGetParameter, Any::class.javaType)
        } catch (e: Exception) {
            e.printStackTrace()
        }

        if (token == null) {
            try {
                imRegisterParameter.appID = "mh.jieyi"
                imRegisterParameter.principal = rsp!!.loginName
                imRegisterParameter.nickName = rsp!!.realName
                token = imRegisterURL.postJson(imRegisterParameter, Any::class.javaType)
            } catch (e: Exception) {
                login.code = ResultCode.ERROR
                login.msg = "注册token失败"
                return login
            }
        }

        loginRsp.person = rsp
        loginRsp.doctor = scheduleRecord
        var sSize = scheduleRecord!!.size
        if (rsp != null && scheduleRecord != null && sSize >= 1 && !requestString.isNullOrEmpty() && token != null) {
            loginRsp.key = requestString
            loginRsp.token = token
            login.code = ResultCode.SUCCESS
            login.msg = "登录成功"
            login.result = loginRsp
            return login
        }
        return login
    }

    @ResponseBody
    @RequestMapping("token")
    fun getToken(@RequestBody map: Map<String, String>): Map<String, Any?>{
        val regMsg = HashMap<String, Any?>()
        var token:Any? =null
        var loginName = map.get("loginName")
        if (loginName.isNullOrEmpty() || loginName.isNullOrBlank()){
            regMsg.put("code", ResultCode.ERROR)
            regMsg.put("msg", "loginName为空！")
            return  regMsg
        }

        var imGetParameter = IMGetParameter()
        imGetParameter.appID = "mh.jieyi"
        imGetParameter.principal =loginName
        var imBase = "https://i.mhwsw.com/im"
        var imGetURL = URL("$imBase/query")

        try {
            token = imGetURL.postJson<Any>(imGetParameter, Any::class.javaType)
            regMsg.put("code", ResultCode.SUCCESS)
            regMsg.put("msg", "查询成功")
            regMsg.put("result", token)

        } catch (e: Exception) {
            e.printStackTrace()
            regMsg.put("code", ResultCode.ERROR)
            regMsg.put("msg", "请重新登录")
        }
        return regMsg
    }

    /**
     * 查询信息ScheduleFilter
     * @return
     */
    @ResponseBody
    @RequestMapping("queryScheduleRecordEx")
    fun queryScheduleRecordEx(@RequestBody map: Map<String, String>): Map<String, Any> {
        val regMsg = HashMap<String, Any>()

        try {
            /* if (StringUtils.isBlank(map.get("begin"))) {
                regMsg.put("code", ResultCode.PARAMETERS_EMPTY);
                regMsg.put("msg", "开始时间不能为空");
            }
            if (StringUtils.isBlank(map.get("end"))) {
                regMsg.put("code", ResultCode.PARAMETERS_EMPTY);
                regMsg.put("msg", "结束时间不能为空");
            }
            if (StringUtils.isBlank(map.get("hospitalCode"))) {
                regMsg.put("code", ResultCode.PARAMETERS_EMPTY);
                regMsg.put("msg", "医院编码不能为空");
            }
            if (StringUtils.isBlank(map.get("deptCode"))) {
                regMsg.put("code", ResultCode.PARAMETERS_EMPTY);
                regMsg.put("msg", "科室编码不能为空");
            }*/
            val docmesslist = cloudAppService!!.queryScheduleRecordEx(map)
            regMsg.put("code", ResultCode.SUCCESS)
            regMsg.put("msg", "查询成功")
            regMsg.put("result", docmesslist)
        } catch (e: Exception) {
            regMsg.put("code", ResultCode.ERROR)
            regMsg.put("msg", "请求出错")
            regMsg.put("error", e.printStackTrace())
            logger.error("查询详情,参数:" + map + "，异常" + e.message, e)
        }

        return regMsg
    }

    /**
     * 通过捷医name查询详情
     * @return
     */
    @ResponseBody
    @RequestMapping("findMessByLogname")
    fun findMessByLogname(@RequestBody map: Map<String, String>): Map<String, Any> {
        val regMsg = HashMap<String, Any>()

        try {
            val logName = map["logName"]
            if (StringUtils.isBlank(logName)) {
                regMsg.put("code", ResultCode.PARAMETERS_EMPTY)
                regMsg.put("msg", "logName不能为空")
            }
            val docmesslist = cloudAppService!!.findMessByLogname(logName)
            regMsg.put("code", ResultCode.SUCCESS)
            regMsg.put("msg", "查询成功")
            regMsg.put("result", docmesslist)
        } catch (e: Exception) {
            regMsg.put("code", ResultCode.ERROR)
            regMsg.put("msg", "请求出错")
            regMsg.put("error", e.printStackTrace())
            logger.error("根据捷医loginname查询详情,参数:" + map + "，异常" + e.message, e)
        }

        return regMsg
    }

    @ResponseBody
    @RequestMapping(value = "upload")
    fun upload(@RequestParam("file") file: MultipartFile):Map<String, Any> {
        val regMsg = HashMap<String, Any>()
        val uuid = UUID.randomUUID().toString()
        val fileKey =appId + uuid
        var df = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        var exec = Executors.newFixedThreadPool(1)
        val completionService = ExecutorCompletionService<String>(exec)
        val task =TaskWithResult(file,appId,secretKey,fileKey,tyURL)
        completionService.submit(task)
        exec.shutdown()
        val completedTask = completionService.take()
        regMsg.put("code", ResultCode.ERROR)
        regMsg.put("msg", "上传失败")
        if(completedTask.isDone){
            var result =getURL+fileKey
            result = completedTask.get()
            regMsg.put("code", ResultCode.SUCCESS)
            regMsg.put("msg", "上传成功")
            regMsg.put("result", result)
            println("Completed a  task - " + result)
        }
        logger.info("返回地址时间:"+ df.format(Date()))
        return regMsg
   }

    @ResponseBody
    @RequestMapping(value = "upload/task")
    fun uploadTask(@RequestParam("file") file: MultipartFile):Map<String, Any> {
        val regMsg = HashMap<String, Any>()
        val uuid = UUID.randomUUID().toString()
        val fileKey =appId + uuid
        var df = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        var exec = Executors.newFixedThreadPool(1)
        val completionService = ExecutorCompletionService<String>(exec)
        val task =EbayMultiplyThreadCheck(file,appId,secretKey,fileKey,tyURL)
        completionService.submit(task)
        exec.shutdown()
        val completedTask = completionService.take()
        regMsg.put("code", ResultCode.ERROR)
        regMsg.put("msg", "上传失败")
        if(completedTask.isDone){
            var result =getURL+fileKey
            regMsg.put("code", ResultCode.SUCCESS)
            regMsg.put("msg", "上传成功")
            regMsg.put("result", result)
            println("Completed a  task - " + result)
        }
        logger.info("返回地址时间:"+ df.format(Date()))
        return regMsg
    }

    @ResponseBody
    @RequestMapping(value = "query/doctorList")
    fun queryDoctorList(@RequestBody map: DoctorParam):Map<String,Any>{
        val regMsg = HashMap<String, Any>()
        regMsg.put("code", ResultCode.ERROR)
        regMsg.put("msg", "没有查询到数据")
        var doctorList = scheduleSiteDao!!.queryDoctorList(map)
        if(doctorList !=null && doctorList.size>0){
            regMsg.put("code", ResultCode.SUCCESS)
            regMsg.put("msg", "查询成功")
            regMsg.put("result", doctorList)
        }
        return regMsg
    }

}

class EbayMultiplyThreadCheck(private val file: MultipartFile, private val appId:String,private val secretKey:String, val fileKey:String, private val tyURL:String): Callable<String>{
    @Throws(Exception::class)
    override fun call():String{
        val exec = Executors.newFixedThreadPool(2)
        val results = ArrayList<Future<String>>()
        for (i in 0..2) {
            results.add(exec.submit(TaskWithResult(file,appId,secretKey,fileKey,tyURL)))
        }
        var isDone = false
        while (!isDone) {
            isDone = true
            for (future in results) {
                if (!future.isDone()) {
                    isDone = false
                    try {
                        Thread.sleep(10000)
                        return "failure"
                    } catch (e: InterruptedException) {
                    }
                    break
                }
            }
        }
        exec.shutdown()
        return "successful"
    }

}


class TaskWithResult(private val file: MultipartFile, private val appId:String,private val secretKey:String, val fileKey:String, private val tyURL:String) : Callable<String> {
    @Throws(Exception::class)
    override fun call(): String {
        var df = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        logger.info("开始上传文件时间:"+ df.format(Date()))
        var url:String
        if (!file.isEmpty) {
            val credentials = BasicAWSCredentials(appId, secretKey)
            val client = AmazonS3Client(credentials)
            client.setEndpoint(tyURL)
            val bucketName = "mh-oos-bucket"

            try {
                var tmpFile = File.createTempFile("tmp", "tmp")
                val output = FileOutputStream(tmpFile)
                val ins = file.inputStream
                tmpFile = File(file.originalFilename)
                FileUtils.inputStreamToFile(ins, tmpFile)
                val metadata = ObjectMetadata()

                metadata.contentType = "multipart/form-data"
                metadata.contentLength = file.size
                metadata.addUserMetadata("x-amz-meta-title", tmpFile.name)
                metadata.contentDisposition = "attachment; filename=" + tmpFile.name

                val putRequest = PutObjectRequest(bucketName, fileKey, FileInputStream(tmpFile), metadata)
                client.putObject(putRequest)
                val obj = client.getObject(GetObjectRequest(bucketName, fileKey))
                val uri = obj.objectContent.httpRequest.uri
                url=uri.toString()
                obj.objectContent.close()
                logger.info("结束上传文件时间:"+ df.format(Date()))
                logger.info("获取地址"+uri.toString())
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
                logger.info("fail1:"+ e.printStackTrace())
                return "upload failure"
            } catch (e: IOException) {
                e.printStackTrace()
                logger.info("fail2:"+ e.printStackTrace())
                return "upload failure"
            }
        } else {
            logger.info("fail3")
            return "upload failure"
        }
        return url
    }

}






